﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Xml.Linq;
using AzukiMap.Map;
using AzukiMap.MapSource;
using AzukiMap.Renderer;
using AzukiMap.Request;
using GeoAPI.Geometries;
using Geometries = GisSharpBlog.NetTopologySuite.Geometries;
using AzukiMap.Tools;

namespace AzukiMap.Layer
{
    public class PostGisRasterIndexLayer : PostGisLayer
    {
        PostGisSource _pgTable;
        //PostGisVectorRequest _pgRequest;
        PostGisRasterIndexRequest _pgRequest;
        PostGisRasterIndexParser _pgParser;
        RasterRenderer _renderer;
        private string _indexColumn;

        public PostGisRasterIndexLayer()
        {
            
        }

        public PostGisRasterIndexLayer(PostGisSource pgTable, string name, Geometries.Polygon extent, string indexColumn)
            : base(pgTable, name, extent)
        {
            Init(pgTable, indexColumn);
        }

        public PostGisRasterIndexLayer(PostGisSource pgTable, string name, string indexColumn)
            : base(pgTable, name)
        {
            Init(pgTable, indexColumn);
        }

        public string BaseUri
        {
            get; set;
        }

        PostGisSource PgTable
        {
            set
            {
                _pgTable = value;
                SetRequest();
            }
            get
            {
                return _pgTable;
            }
        }

        string IndexColumn
        {
            set
            {
                _indexColumn = value;
                SetRequest();
            }
            get
            {
                return _indexColumn;
            }
        }

        void SetRequest()
        {
            if (_pgTable != null && _indexColumn != null)
            {
                if (_pgTable.GetColumnDataUri != null)
                {
                    _pgRequest = new PostGisRasterIndexRequest(this, _pgTable.GetColumnDataUri, _indexColumn);
                }
                else
                {
                    _pgRequest = new PostGisRasterIndexRequest(this, _indexColumn);
                }
                _pgRequest.GetDataCompleted += new GetDataCompletedHandler(_pgRequest_GetDataCompleted);
                _renderer = new RasterRenderer(this);
            }
        }

        void Init(PostGisSource pgTable, string indexColumn)
        {
            _pgTable = pgTable;
            _indexColumn = indexColumn;
            SetRequest();
        }

        public override void Draw()
        {
            SetCopyrightVisibility(IsDrawable ? Visibility.Visible : Visibility.Collapsed);

            // return when not drawable
            if (!IsDrawable)
            {
                return;
            }

            if ((!base.IsRendering && base.IsVisible) && base.CheckScale())
            {
                base.IsRendering = true;
                this._pgRequest.Request();
            }
        }

        public override void Redraw()
        {
            if (IsRendering)
            {
                return;
            }
            Clear();
            IsRendering = true;
            _pgRequest.Request();
        }

        void _pgRequest_GetDataCompleted(object sender, GetDataCompletedArgs e)
        {
            this._pgParser = new PostGisRasterIndexParser(e.DataStream);
            int numOfGeom = this._pgParser.NumOfObjects;
            foreach (RasterIndexRecord record in this._pgParser.Records)
            {
                if (record.Extent.Geometries.Length == 0)
                {
                    continue;
                }

                var area = (IPolygon) record.Extent.GetGeometryN(0);
                IList<FrameworkElement> images =
                    this._renderer.Draw(
                        new Uri(this.BaseUri + "/" + record.RasterIndex, UriKind.RelativeOrAbsolute), area);

                RenderedElements[record.Id] = images;

                foreach (FrameworkElement img in images)
                {
                    base.Children.Add(img);
                }
            }
            base.IsRendering = false;
        }

        public override XElement ToXml()
        {
            return ToXml("PostGisRasterIndexLayer");
        }

        public override XElement ToXml(string elementName)
        {
            XElement postGisRasterIndexLayerXml = base.ToXml(elementName);

            postGisRasterIndexLayerXml.Add(
                _xmlCommon.CreateAttr("IndexColumn", _indexColumn),
                _xmlCommon.CreateElement("BaseUri", BaseUri)
                );
            return postGisRasterIndexLayerXml;
        }

        public override void Parse(XElement layerXml)
        {
            base.Parse(layerXml);
            PgTable = PgSource;
            BaseUri = _xmlCommon.GetStringElement(layerXml, "BaseUri");
            IndexColumn = _xmlCommon.GetStringAttr(layerXml, "IndexColumn");
        }
    }
}
